﻿/*
     Author: GhostBear
 *   Blog: http://blog.csdn.net/ghostbear
 *   Date: 2013-4-16
 *   Description:  This tool can generate client object's json string accroding to the entity's metadata.In many times we spend
 *                 much time to adjust the json string when we create/update entity using REST in client side.To resolve 
 *                 it I build a tool named MagicBox. We only need to fill a few coded to figure out which entity need to be used, and 
 *                 click 'Go' button. Then program will generate json string automaticlly.
 *   Example:
 *          Step 1: Configure the file App.config  to set these configurations: orgSvcPath, invokerAccount, invokerAccountPwd, invokerDomain.
 *          Step 2: Complete the function  GenerateEntity()'s codes to figure out which entity you want to use.
 *          Step 3: Lanuch MagicBox
 *          Step 4: Click Go button
 */
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Metadata;

namespace MagicBox
{
    public partial class Form1 : Form
    {
        private static Dictionary<string, EntityMetadata> EntityMetaDataTable=new Dictionary<string,EntityMetadata>();
        public Form1()
        {
            InitializeComponent();
            
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            
        }

        private Entity GenerateEntity()
        {
            //Type your codes to retrieve a entity which you want to use.
            //Start

            IOrganizationService svc = CommonLibrary.CrmSvcHelper.CreateService();
            Guid entityId = Guid.Parse("{204B9D72-20A7-E211-B2BE-00155D1CE815}");
            return svc.Retrieve("ms_fighter", entityId, new Microsoft.Xrm.Sdk.Query.ColumnSet(true));

            //End
        }

        private string GenerateSerializationString(Entity entity)
        {
            StringBuilder result = new StringBuilder();
            string tmp=string.Empty;
            Microsoft.Xrm.Sdk.AttributeCollection attributes = entity.Attributes;
            AttributeMetadata attrMetadata=null;
            result.Append("{");
            foreach (var item in attributes)
            {
                attrMetadata=GetAttributeMetadata(entity.LogicalName,item.Key);
                switch (attrMetadata.AttributeType.Value)
                {
                    case AttributeTypeCode.BigInt:
                        result.Append(string.Format("'{0}':'{1}'", attrMetadata.SchemaName, item.Value));
                        result.Append(",");
                        break;
                    case AttributeTypeCode.Boolean:
                        result.Append(string.Format("'{0}':'{1}'", attrMetadata.SchemaName, item.Value));
                        result.Append(",");
                        break;
                    case AttributeTypeCode.CalendarRules:
                        break;
                    case AttributeTypeCode.Customer:

                        break;
                    case AttributeTypeCode.DateTime:
                        result.Append(string.Format("'{0}':'{1}'", attrMetadata.SchemaName, item.Value));
                        result.Append(",");
                        break;
                    case AttributeTypeCode.Decimal:
                        result.Append(string.Format("'{0}':'{1}'", attrMetadata.SchemaName, item.Value));
                        result.Append(",");
                        break;
                    case AttributeTypeCode.Double:
                        result.Append(string.Format("'{0}':'{1}'", attrMetadata.SchemaName, item.Value));
                        result.Append(",");
                        break;
                    case AttributeTypeCode.EntityName:
                        break;
                    case AttributeTypeCode.Integer:
                         result.Append(string.Format("'{0}':'{1}'", attrMetadata.SchemaName, item.Value));
                        result.Append(",");
                        break;
                    case AttributeTypeCode.Lookup:
                        result.Append(string.Format("'{0}':{{'LogicalName':'{1}','Id':'{2}'}}", attrMetadata.SchemaName, ((EntityReference)item.Value).LogicalName, ((EntityReference)item.Value).Id));
                        result.Append(",");
                        break;
                    case AttributeTypeCode.ManagedProperty:
                        break;
                    case AttributeTypeCode.Memo:
                        break;
                    case AttributeTypeCode.Money:
                        result.Append(string.Format("'{0}':{{'Value':'{1}'}}", attrMetadata.SchemaName, ((Money)item.Value).Value));
                        result.Append(",");
                        break;
                    case AttributeTypeCode.Owner:
                        result.Append(string.Format("'{0}':{{'LogicalName':'{1}','Id':'{2}'}}", attrMetadata.SchemaName, ((EntityReference)item.Value).LogicalName, ((EntityReference)item.Value).Id));
                        result.Append(",");
                        break;
                    case AttributeTypeCode.PartyList:
                        break;
                    case AttributeTypeCode.Picklist:
                        result.Append(string.Format("'{0}':{{'Value':'{1}'}}", attrMetadata.SchemaName, ((OptionSetValue)item.Value).Value));
                        result.Append(",");
                        break;
                    case AttributeTypeCode.State:
                        result.Append(string.Format("'{0}':{{'Value':'{1}'}}", attrMetadata.SchemaName, ((OptionSetValue)item.Value).Value));
                        result.Append(",");
                        break;
                    case AttributeTypeCode.Status:
                        result.Append(string.Format("'{0}':{{'Value':'{1}'}}", attrMetadata.SchemaName, ((OptionSetValue)item.Value).Value));
                        result.Append(",");
                        break;
                    case AttributeTypeCode.String:
                        result.Append(string.Format("'{0}':'{1}'",attrMetadata.SchemaName,item.Value));
                        result.Append(",");
                        break;
                    case AttributeTypeCode.Uniqueidentifier:
                        result.Append(string.Format("'{0}':'{1}'", attrMetadata.SchemaName, item.Value));
                        result.Append(",");
                        break;
                    case AttributeTypeCode.Virtual:
                        break;
                    default:
                        break;
                }
            }
            
            tmp=result.ToString();
            return tmp.Substring(0, tmp.Length - 1) + "}";// remove the last ,
        }



        private EntityMetadata GetEntityMetadata(string entityName)
        {
            if(EntityMetaDataTable.ContainsKey(entityName)==false)
            {
                IOrganizationService svc = CommonLibrary.CrmSvcHelper.CreateService();
                RetrieveEntityRequest request = new RetrieveEntityRequest();
                request.EntityFilters = EntityFilters.Attributes;
                request.LogicalName = entityName;

                RetrieveEntityResponse response = svc.Execute(request) as RetrieveEntityResponse;
                if (response != null && response.EntityMetadata != null)
                {
                    EntityMetaDataTable.Add(entityName, response.EntityMetadata);
                }
                else
                {
                    return null;
                }
            }

            return EntityMetaDataTable[entityName];

            
            
        }

        private AttributeMetadata GetAttributeMetadata(string entityname, string attrName)
        {
            EntityMetadata metadata = GetEntityMetadata(entityname);
            if (metadata == null)
            {
                MessageBox.Show("incorrect entity name");

            }
            var list = metadata.Attributes.Where((m) => m.SchemaName.ToLower() == attrName.ToLower()).ToList();
            if (list.Count() == 0)
            {
                MessageBox.Show("incorrect attribute name");

            }
            return list[0];
           
            
            
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                richTextBox1.Text= GenerateSerializationString(GenerateEntity());
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }
}
